package immigration;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.LinkedList;
import mdr.RecommendGenerator;
import model.StatementKind;
import operations.Operation;
import instrumentation.TrackerCoverage;
import ga.Individual;
public class ElitismBasedImmigration extends ImmigrationStrategy {

	@Override
	public Set<Individual> getImmigrant(){

		Set<Individual> imigrantIndividuals=new HashSet<Individual>();
		TrackerCoverage  tracker=this.gaInfo.getTracker();
		Set<Integer> notCoveredBranches=tracker.branchNotCoveredByIndividual.keySet();
		for (Integer br : tracker.branchesBasedDistance.keySet()) {
	//		br=21;
			if(tracker.branchesBasedDistance.get(br)==0) continue;
			Individual individual = tracker.branchNotCoveredByIndividual.get(br).clone();			
			individual=this.mutate(individual,br);
			imigrantIndividuals.add(individual);
			
		}
		return imigrantIndividuals;
	}

	public Individual mutate(Individual  individual,int br) {
		RecommendGenerator recommendGenerator=this.gaInfo.getRecommendGenerator();

		Map<Class<?>,  List<StatementKind>> recommendMethods=recommendGenerator.getRecommendMethodsBranch(br);
		recommendGenerator.displayCondition(br, individual,recommendMethods);
		//get the reciver of the MUT
		Operation lastCall=individual.getStatements().get(individual.getSize()-1);
		String ref=null;
		if(lastCall instanceof operations.InvokeMethod){
			operations.InvokeMethod m = (operations.InvokeMethod) lastCall;
			ref= m.getThis();
		}
		
		
		
		List<Operation> ops=new LinkedList<Operation>(individual.getStatements());
		List<Operation> newOps=null;
		if(recommendMethods.size()!=0)
			newOps=	Operation.mdrGenerateOperation(gaInfo.getTestCluster(),ref,10,recommendMethods);
		else
			newOps=	Operation.randomlyGenerateOperation(gaInfo.getTestCluster(), 10);
			
		List<Operation> rep = new LinkedList<Operation>();
		
		int pos=ops.size()-1;
		rep.addAll(ops.subList(0, pos));
		rep.addAll(newOps.subList(0, newOps.size()));
		rep.addAll(ops.subList(pos, ops.size()));
		ops.clear();
		ops.addAll(rep.subList(0, rep.size()));
		
		return new Individual(individual.getInitialConstructors(),ops);
	}

}
